// Copyright (C) joyinter
// All rights reserved.
// 
// Author : Jiang Li
// Date   : 2004-11-15

#include "stdafx.h"
#include "svr_msgwnd.h"

namespace JoyServer
{

#define MSG_EXEC (WM_USER+0x33)

// class CJoyMsgWnd

CJoyMsgWnd::CJoyMsgWnd()
{
    m_hWnd      = NULL;
    m_threadId  = 0;
}

CJoyMsgWnd::~CJoyMsgWnd()
{
}

LRESULT WINAPI CJoyMsgWnd::sWindowProc(HWND hWnd, UINT nMessage, WPARAM wParam, LPARAM lParam)
{
    if(nMessage == MSG_EXEC)
    {
        CJoyMsgWnd* pWnd = (CJoyMsgWnd*)wParam;
        pWnd->ProcessExecs();
        return 0;
    }
    return DefWindowProc(hWnd, nMessage, wParam, lParam);
}

void CJoyMsgWnd::OnMessage(UINT nMessage, void* pContext)
{
    nMessage;pContext;
}

PCSTR CJoyMsgWnd::GetWindowClass()
{
    static char* wndClsName = "JoyServerMessageWindowClass";
    WNDCLASS wc;
    wc.style        = 0;
    wc.lpfnWndProc  = sWindowProc;
    wc.cbClsExtra   = 0;
    wc.cbWndExtra   = 0;
    wc.hInstance    = GetModuleHandle(NULL);
    wc.hIcon        = NULL;
    wc.hCursor      = NULL;
    wc.hbrBackground= NULL;
    wc.lpszMenuName = NULL;
    wc.lpszClassName= wndClsName;

    RegisterClass(&wc);
    return wndClsName;
}

bool CJoyMsgWnd::Create()
{
    static PCSTR wndClsName = GetWindowClass();

    m_hWnd = CreateWindow(wndClsName, NULL, 0, 0, 0, 10, 10, HWND_MESSAGE , NULL, GetModuleHandle(NULL), NULL);
    if(m_hWnd == NULL)
    {
        return false;
    }
    m_threadId = GetCurrentThreadId();
    return true;
}

void CJoyMsgWnd::Destroy()
{
    {
        CJoyAutoCS gate(m_lock);
        POSITION pos = m_execs.GetHeadPosition();
        while(pos != NULL)
        {
            CJoyMsgWndExec* pExec = m_execs.GetNext(pos);
            delete pExec;
        }
        m_execs.RemoveAll();
    }

    if(m_hWnd != NULL)
    {
        DestroyWindow(m_hWnd);
        m_hWnd = NULL;
    }
}

void CJoyMsgWnd::ProcessExecs()
{
    {
        CJoyAutoCS gate(m_lock);
        while(!m_execs.IsEmpty())
        {
            m_tempExecs.AddTail(m_execs.RemoveHead());
        }
    }

    POSITION pos = m_tempExecs.GetHeadPosition();
    while(pos != NULL)
    {
        CJoyMsgWndExec* pExec = m_tempExecs.GetNext(pos);
        pExec->Execute();
        delete pExec;
    }
    m_tempExecs.RemoveAll();
}

void CJoyMsgWnd::PostExec(CJoyMsgWndExec* exec)
{
    m_lock.Lock();
    BOOL b = m_execs.IsEmpty();
    m_execs.AddTail(exec);
    m_lock.Unlock();

    if(b)
    {
        PostMessage(m_hWnd, MSG_EXEC, (WPARAM)this, 0);

        if(m_threadId == GetCurrentThreadId())
        {
            MSG msg;
            while(::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
            {
                ::TranslateMessage(&msg);
                ::DispatchMessage(&msg);
            }
        }
    }
}

} // namespace JoyServer